package com.example.publice.aspect;


import com.alibaba.fastjson.JSON;
import com.example.admin.entity.SysOperateLog;
import com.example.publice.aspect.annotation.Log;
import com.example.shrio.CurrentUser;
import com.example.util.address.AddressUtils;
import com.example.util.address.IpUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

/**
 * 操作日志
 */
@Aspect
@Component
public class LogAspect {


    @Pointcut("@annotation(com.example.publice.aspect.annotation.Log)")
    public void logPointCut() {
    }

    /**
     * 响应后操作
     *
     * @param joinPoint  切点
     * @param jsonResult 返回数据
     */
    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {

        insert(joinPoint, null, jsonResult);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {

        insert(joinPoint, e, null);
    }

    private void insert(JoinPoint joinPoint, Exception e, Object jsonResult) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        Log log = method.getAnnotation(Log.class);
        SysOperateLog operateLog = new SysOperateLog();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        operateLog.setMethod(className + "." + methodName + "()");
        operateLog.setRequestMethod(request.getMethod());
        operateLog.setOperName(CurrentUser.getAdminUser().getRealName());
        operateLog.setOperUrl(request.getRequestURI());
        operateLog.setOperIp(IpUtils.getIpAddr(request));
        operateLog.setOperLocation(AddressUtils.getRealAddressByIP(operateLog.getOperIp()));
        String requestMethod = operateLog.getRequestMethod();
        if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
            operateLog.setOperParam(JSON.toJSONString(joinPoint.getArgs()));
        } else {
            Map<?, ?> paramsMap = (Map<?, ?>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            operateLog.setOperParam(JSON.toJSONString(paramsMap));
        }
        operateLog.setJsonResult(JSON.toJSONString(jsonResult));
        operateLog.setTitle(log.title());
        operateLog.setBusinessType(log.businessType().getCode());
        operateLog.setStatus(0);
        if (e != null) {
            operateLog.setStatus(1);
            operateLog.setErrorMsg(e.getMessage());
        }
        operateLog.setOperTime(new Date());
        operateLog.insert();
    }

}
